This specification relates to static analysis of software source code.
Static analysis refers to techniques for analyzing computer software source code without executing the source code as a computer software program. Static analysis systems analyze source code to determine various properties about source code in a code base.
Static analysis systems can identify characteristic segments of source code in the code base. A characteristic segment of source code is a segment of source code having a particular attribute of interest. Static analysis systems can generate analysis results that include data specifying where, in the code base, the characteristic segments of source code occur.
Static analysis systems can uniquely distinguish one source code element from another using keys. The keys can be used to maintain attributes of source code elements in a database.
A natural database key is a key that can be computed from attributes of the data that the key identifies. In other words, a natural key can be computed from the data regardless of how the data is stored in a database. For example, a person's phone number is often used as a natural key for distinguishing the person from other people in the database. The phone number does not change if the underlying structure of the data is changed or if the database is rebuilt. In contrast, surrogate keys are keys that are generated by arbitrary assignment, often coming from a source unrelated to the data being identified. For example, keys that are generated sequentially are surrogate keys.
Some programming languages, e.g., Java, support annotations. An annotation is a programming construct for associating arbitrary, structured, and unordered metadata with source code elements. In many cases, annotations do not affect how a program executes, but annotations may affect how a program is compiled. Annotations can be attached to a variety of source elements, e.g., classes, fields, methods, variables, parameters, packages, or other source code elements.
An annotation may have one or more arguments. Each argument can be named or unnamed, and each argument can have a corresponding value. Annotations can also be nested. In other words, an argument within an annotation may be another annotation.
The following segment of source code illustrates an annotation that is defined in source code preceding the definition of the class “Test”:
@ExampleAnnot {                name=“Kirk”,        addresses={“Address 1”, “Address 2”},        nestedAnnot=@Name(name=“Bones”)        
}
class Test{ . . .
This annotation, ExampleAnnot, includes three arguments—a string, an array, and a nested annotation. The string argument indicates that the class “Test” has associated metadata having an identifier “name” with a value of “Kirk”. The array argument indicates that the class “Test” has associated metadata having an identifier “addresses”, which identifies an array having respective values of “Address 1”, and “Address2”. The nested annotation argument indicates that the class “Test” has associated metadata having an identifier “nestedAnnot”, which itself identifies a nested annotation named “Name”. The nested annotation has a string argument having an identifier “name” and having the value “Bones”.
When the value of an annotation argument is a nested annotation, the name of the nested annotation need not be unique within the top-level annotation. In other words, the annotation ExampleAnnot could validly have another argument that is a nested annotation named “Name.” Furthermore, the second nested annotation could also have a string argument having an identifier “name” and having a value of “Bones.” Thus, even in this simple example, the identifier “name” may occur as an argument identifier three times within this simple top-level annotation.